using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;

namespace ScannerLib.Tsai
{
    public static class Calibrator
    {
        public static CameraCalibrationData CalibrateCamera(List<CalibrationPoint> calibrationPoints)
        {
            StreamWriter sw = new StreamWriter(Application.StartupPath + "\\" + "calib.points");

            foreach (CalibrationPoint cp in calibrationPoints)
            {
                sw.WriteLine(cp.PX + " " + cp.PY + " 0 " + cp.X + " " + cp.Y);
            }

            sw.Close();
            sw.Dispose();

            
            Process p = new Process();
            p.StartInfo.FileName = Application.StartupPath + "\\" + "ccal.exe";
            p.StartInfo.Arguments = "calib.points";
            p.StartInfo.WorkingDirectory = Application.StartupPath;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardError = false;
            p.StartInfo.RedirectStandardOutput = true;

            p.Start();

            string s = p.StandardOutput.ReadToEnd();

            p.Dispose();

            return new CameraCalibrationData(new StringReader(s));
        }

        public static bool CalibrateLight(CameraCalibrationData camCalibrationData, List<PointPair> calibrationPoints)
        {
            StreamWriter sw = new StreamWriter(Application.StartupPath + "\\"+ "lcalib.points");

            foreach (PointPair cp in calibrationPoints)
            {
                sw.WriteLine(cp.Start.X + " " + cp.Start.Y + " " + cp.End.X + " " + cp.End.Y);
            }

            sw.Close();
            sw.Dispose();

            sw = new StreamWriter(Application.StartupPath + "\\" + "lcalib.camdata");

            sw.Write(camCalibrationData.OriginalDataFile);

            sw.Close();
            sw.Dispose();

            Process p = new Process();
            p.StartInfo.FileName = Application.StartupPath + "\\" + "ligthcal.exe";
            p.StartInfo.Arguments = "lcalib.points lcalib.camdata";
            p.StartInfo.WorkingDirectory = Application.StartupPath;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardError = false;
            p.StartInfo.RedirectStandardOutput = true;

            p.Start();

            string s = p.StandardOutput.ReadToEnd();

            while (!p.HasExited)
                Thread.Sleep(50);

            if (p.ExitCode != 0)
                return false;

            p.Dispose();

            StringReader sr = new StringReader(s);

            double x = Convert.ToDouble(sr.ReadLine());
            double y = Convert.ToDouble(sr.ReadLine());
            double z = Convert.ToDouble(sr.ReadLine());

            camCalibrationData.LightCalibrationData = new ScannerLib.Vector.BasicVector(x, y, z);

            return true;
        }

        public static bool CreateModel(CameraCalibrationData camCalibrationData,string framepath)
        {
            StreamWriter sw = new StreamWriter(Application.StartupPath + "\\" + "model.camdata");

            sw.WriteLine(camCalibrationData.LightCalibrationData.X);
            sw.WriteLine(camCalibrationData.LightCalibrationData.Y);
            sw.WriteLine(camCalibrationData.LightCalibrationData.Z);
            sw.Write(camCalibrationData.OriginalDataFile);
            

            sw.Close();
            sw.Dispose();

            Process p = new Process();
            p.StartInfo.FileName = Application.StartupPath + "\\" + "modelgen.exe";
            p.StartInfo.Arguments = "model.camdata " + framepath;
            p.StartInfo.WorkingDirectory = Application.StartupPath;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardError = false;
            p.StartInfo.RedirectStandardOutput = false;

            p.Start();

            string s = p.StandardOutput.ReadToEnd();

            while (!p.HasExited)
                Thread.Sleep(50);

            if (p.ExitCode != 0)
            {
                p.Dispose();
                return false;
            }
            p.Dispose();

            
            return true;
        }
    }
}
